﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;

namespace Trentacular.Office.Server.Search.FacetedSearch
{
    /// <summary>
    /// Represents the context for a faceted search.
    /// </summary>
    public class FacetedSearchContext
    {
        private Dictionary<Guid, IList<string>> _activeFacets =
            new Dictionary<Guid, IList<string>>();

        /// <summary>
        /// Adds an active facet to the context.
        /// </summary>
        /// <param name="configurationID">The configuration ID of the facet provider
        /// that generated the facet.</param>
        /// <param name="facetKey">The facet key.</param>
        public void AddActiveFacet(Guid configurationID, string facetKey)
        {
            if (_activeFacets.ContainsKey(configurationID))
                _activeFacets[configurationID].Add(facetKey);
            else
                _activeFacets[configurationID] = new List<string> { facetKey };
        }

        /// <summary>
        /// Removes an active facet from the context.
        /// </summary>
        /// <param name="configurationID">The configuration ID of the facet provider
        /// that generated the facet.</param>
        /// <param name="facetKey">The facet key.</param>
        public void RemoveActiveFacet(Guid configurationID, string facetKey)
        {
            if (_activeFacets.ContainsKey(configurationID))
            {
                var activeKeys = _activeFacets[configurationID];
                activeKeys.Remove(facetKey);

                if (activeKeys.Count == 0)
                    _activeFacets.Remove(configurationID);
            }
        }

        /// <summary>
        /// Determines whether the specified facet is active.
        /// </summary>
        /// <param name="facet">The facet.</param>
        /// <returns>
        /// 	<c>true</c> if the specified facet is active; otherwise, <c>false</c>.
        /// </returns>
        public bool IsActiveFacet(Facet facet)
        {
            return _activeFacets.ContainsKey(facet.Configuration.ID) &&
                _activeFacets[facet.Configuration.ID].Contains(facet.Key);
        }

        /// <summary>
        /// The ViewState Key used to locate the FacetedSearchContext.
        /// </summary>
        public const string ViewStateKey = "FacetedSearchContext";

        /// <summary>
        /// Saves this context to the given ViewState state bag.
        /// </summary>
        /// <param name="viewState">ViewState of a control to save this context to.
        /// </param>
        public void SaveToViewState(StateBag viewState)
        {
            var activeFacets = new Hashtable();
            foreach (var configurationID in _activeFacets.Keys)
            {
                activeFacets[configurationID] =
                    _activeFacets[configurationID].ToArray();
            }
            viewState[ViewStateKey] = activeFacets;
        }

        /// <summary>
        /// Loads the faceted search context of from the given ViewState state bag.
        /// </summary>
        /// <param name="viewState">ViewState of a control to load the context from.
        /// </param>
        /// <returns>The faceted search context from the given ViewState.</returns>
        public static FacetedSearchContext LoadFromViewState(StateBag viewState)
        {
            var facetedSearchContext = new FacetedSearchContext();

            var activeFacets = viewState[ViewStateKey] as Hashtable;
            if (activeFacets != null)
            {
                foreach (Guid configurationID in activeFacets.Keys)
                {
                    var facetKeys = activeFacets[configurationID] as string[];
                    foreach (var key in facetKeys)
                    {
                        facetedSearchContext.AddActiveFacet(configurationID, key);
                    }
                }
            }

            return facetedSearchContext;
        }
    }
}
